package commons.base.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

public class AcceptWorker implements Runnable, AutoCloseable {

	private Selector selector;
	private IOWorkerGroup ioWorkerGroup;
	private ServerSocketChannel ssc;
	private AtomicBoolean running = new AtomicBoolean(true);
	
	public AcceptWorker(SelectorProvider selectorProvider, IOWorkerGroup ioWorkerGroup) throws IOException{
		selector = selectorProvider.openSelector();
		this.ioWorkerGroup = ioWorkerGroup;
	}
	
	public void bind(InetSocketAddress socketAddress) throws IOException{
		ssc = ServerSocketChannel.open();
		ssc.configureBlocking(false);
		ssc.socket().bind(socketAddress);
		
		// 注册感兴趣的事件，此处对accpet事件感兴趣
		ssc.register(selector, SelectionKey.OP_ACCEPT);
	}
	
	@Override
	public void run() {
		try {
			while (running.get()) {
				selector.select();
				Set<SelectionKey> readyKeys = selector.selectedKeys();
				Iterator<SelectionKey> i = readyKeys.iterator();
				
				while (i.hasNext()) {
					SelectionKey sk = (SelectionKey) i.next();
					i.remove();
					if (sk.isAcceptable()) {
						doAccept(sk);
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
	
	private void doAccept(SelectionKey sk) {
		ServerSocketChannel server = (ServerSocketChannel) sk.channel();
		
		try {
			ioWorkerGroup.chooseWorker().regist(server.accept());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void close() throws Exception {
		running.set(false);
		
		try {
			selector.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		if(ssc != null){
			try {
				ssc.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

}
